fix: complete generic function call defaults - #1535
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e7c5774d68
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
1ec4a80 to
968caff
Compare
|
@codex review |
968caff to
31a78ff
Compare
Complete omitted generic arguments at function call sites, preserve inherent Self defaults, validate generic const defaults, and keep callable default layout identity.
Keep default bindings and owner bounds, reject invalid recovered const bodies before CTFE, preserve stored function item values, lower defaults in declaration-owned templates, canonicalize semantic array length identities, and keep default-hole declaration provenance.
Bind generic default templates to declaration schemas with checked const boundaries, verify selected call signatures, provider and receiver context under retained evidence, preserve generic layout capture context and concrete array extents across HIR and MIR, finalize generated runtime calls through the shared callee finalizer, and replace HIR/IR probe tests with Fe runtime fixtures.
97db40b to
2a9dc27
Compare
Share schema substitution, inherited formal lookup, trait-evidence normalization, and semantic call-site planning. Consolidate redundant Rust probes into Fe runtime and diagnostic fixtures for recursive defaults and associated trait arguments.
0a94db6 to
39a019b
Compare
Mainline #1535 builds `Self::Out` inside a generic trait from all of the trait's parameters, so `impl<A, P: T<A>> T<A> for Wrap<P>` with `fn f(_ a: A) -> Self::Out` now type-checks. Its fixture covers bare associated names on concrete impls; these fixtures cover an impl that stays generic over the trait's parameter. The fe test fixture runs such an impl end to end. The type check fixture keeps the diagnostic for a genuinely wrong return type, which names the impl's actual `(P::Out, A)` instead of `Wrap<P>::Out`.
An explicit const argument such as the `3` in `Window<1> {}.take<3>()`
or `Window<1>::sum<3>()` must be evaluated against the parameter's type,
as a free function's is, so that constant evaluation of a method or
associated function can read its const parameter.
#1535 made this so: explicit call arguments of every function, methods
included, now go through the generic parameter schema's completion,
which evaluates them. Before #1535 such a constant panicked with
"instantiated constant template retains its value description". This
`fe test` fixture pins that behavior for methods and associated
functions.
An explicit const argument such as the `3` in `Window<1> {}.take<3>()`
or `Window<1>::sum<3>()` must be evaluated against the parameter's type,
as a free function's is, so that constant evaluation of a method or
associated function can read its const parameter.
#1535 made this so: explicit call arguments of every function, methods
included, now go through the generic parameter schema's completion,
which evaluates them. Before #1535 such a constant panicked with
"instantiated constant template retains its value description". This
`fe test` fixture pins that behavior for methods and associated
functions.
`caller_args` rebases a method body's inferred arguments onto the method's own formals, so they compare with the caller's premises in one basis. When that substitution failed it silently returned the arguments unchanged (`.unwrap_or(args)`), while the equivalent failure one step later, instantiating the requirement (`requirement_subst`), makes the discharge fail. Comparing in two bases could miss a premise, or match one it should not. `caller_args` now returns `Result<_, SubstError>`, mainline's typed substitution error, and `caller_premises` propagates it with `?`, the way #1535's `MethodArgMapError` results are threaded through method argument mapping. Discharge turns either failure into `RequirementFailure::NotInstantiable`, as it does for `requirement_subst`. No fixture reaches the failing substitution; no snapshot changes (log 39).
An explicit const argument such as the `3` in `Window<1> {}.take<3>()`
or `Window<1>::sum<3>()` must be evaluated against the parameter's type,
as a free function's is, so that constant evaluation of a method or
associated function can read its const parameter.
#1535 made this so: explicit call arguments of every function, methods
included, now go through the generic parameter schema's completion,
which evaluates them. Before #1535 such a constant panicked with
"instantiated constant template retains its value description". This
`fe test` fixture pins that behavior for methods and associated
functions.
`caller_args` rebases a method body's inferred arguments onto the method's own formals, so they compare with the caller's premises in one basis. When that substitution failed it silently returned the arguments unchanged (`.unwrap_or(args)`), while the equivalent failure one step later, instantiating the requirement (`requirement_subst`), makes the discharge fail. Comparing in two bases could miss a premise, or match one it should not. `caller_args` now returns `Result<_, SubstError>`, mainline's typed substitution error, and `caller_premises` propagates it with `?`, the way #1535's `MethodArgMapError` results are threaded through method argument mapping. Discharge turns either failure into `RequirementFailure::NotInstantiable`, as it does for `requirement_subst`. No fixture reaches the failing substitution; no snapshot changes (log 39).
An explicit const argument such as the `3` in `Window<1> {}.take<3>()`
or `Window<1>::sum<3>()` must be evaluated against the parameter's type,
as a free function's is, so that constant evaluation of a method or
associated function can read its const parameter.
#1535 made this so: explicit call arguments of every function, methods
included, now go through the generic parameter schema's completion,
which evaluates them. Before #1535 such a constant panicked with
"instantiated constant template retains its value description". This
`fe test` fixture pins that behavior for methods and associated
functions.
`caller_args` rebases a method body's inferred arguments onto the method's own formals, so they compare with the caller's premises in one basis. When that substitution failed it silently returned the arguments unchanged (`.unwrap_or(args)`), while the equivalent failure one step later, instantiating the requirement (`requirement_subst`), makes the discharge fail. Comparing in two bases could miss a premise, or match one it should not. `caller_args` now returns `Result<_, SubstError>`, mainline's typed substitution error, and `caller_premises` propagates it with `?`, the way #1535's `MethodArgMapError` results are threaded through method argument mapping. Discharge turns either failure into `RequirementFailure::NotInstantiable`, as it does for `requirement_subst`. No fixture reaches the failing substitution; no snapshot changes (log 39).
`fn f(a: Holder<{ id<5>() }>::Out, b: Holder<{ id<5>() }>::Out)` made
the compiler panic with a query cycle. Building f's parameter list
lowers its parameter types. Resolving `::Out` type-checks the const
block, which evaluates the `5` in `id<5>`. That evaluation built its
capture environment up front, which asks for f's parameter list again.
Since #1535 the capture environment is built at the start of
evaluate_const_ty, even for a literal or arithmetic that never reads
it. Build it on first use instead. The value is the same wherever it
is used, so results do not change; only the needless dependency goes
away. A const block passed as a generic argument inside such a
parameter type (`id<{ id<5>() }>`) still needs the environment and
still cycles; that is left for a separate change.
`fn f(a: Holder<{ id<5>() }>::Out, b: Holder<{ id<5>() }>::Out)` made
the compiler panic with a query cycle. Building f's parameter list
lowers its parameter types. Resolving `::Out` type-checks the const
block, which evaluates the `5` in `id<5>`. That evaluation built its
capture environment up front, which asks for f's parameter list again.
Since #1535 the capture environment is built at the start of
evaluate_const_ty, even for a literal or arithmetic that never reads
it. Build it on first use instead. The value is the same wherever it
is used, so results do not change; only the needless dependency goes
away. A const block passed as a generic argument inside such a
parameter type (`id<{ id<5>() }>`) still needs the environment and
still cycles; that is left for a separate change.
Completes omitted generic function arguments from trailing type and const defaults.
Also:
Selfdefaults and captured generic bindings through lowering= _defaults distinct call-site layout identities and preserves dependent roots